package com.hup.utils.commons.hardware;

import com.hup.utils.commons.JniUtil;

import java.awt.Desktop;
import java.awt.Point;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * 说明详见说明文本 /dll/HRobotJni.dll.txt
 *
 * @author hugan
 * @date 2020/11/3
 */
public class HRobotJni {
    static {
        JniUtil.loadLibraryJni("/dll/HRobotJni.dll");
    }

    /**
     * 版本号
     */
    public static native String version();

    /**
     * 移动鼠标
     *
     * @apiNote 移动失败的情况:任务管理器,管理员运行的[微信,jar程序]
     */
    public static native boolean mouseMove(int x, int y);

    /**
     * 显示鼠标; 解决开机/重新登陆时,不移动物理鼠标时,系统不显示鼠标光标
     */
    public static native boolean showMouse();

    /**
     * {@link #mouseMove(int, int)}
     */
    public static boolean mouseMove(Point p) {
        return mouseMove(p.x, p.y);
    }

    /**
     * 模拟滚轮滚动
     *
     * @param value 滚动n个单位的距离,取值非零整数:小于0表示向上/左
     * @param isHorizontal false-竖直滚动;true-水平滚动
     */
    public static native boolean mouseWheel(int value, boolean isHorizontal);

    /**
     * 切换媒体[播放/暂停](能控制谷歌浏览器);
     * .使用激活虚拟按键的方式
     */
    public static native void mediaPlayPause();

    /**
     * 模拟按键
     *
     * @param keyCode 来源[winuser.h], 如[VK_MEDIA_STOP]的值
     */
    public static native int clickKey(int keyCode);

    /**
     * 获取键盘灯开关状态
     * @return byte[00000111],右边n位分别代表[VK_SCROLL,VK_CAPITAL,VK_NUMLOCK]的开关状态
     */
    public static native byte getKeyboardState();

    /**
     * 锁屏
     *
     * @apiNote 无管理员权限问题
     */
    public static native void lockWorkStation();

    //========VolumeUtil

    /**
     * 创建全局变量VolumeUtil;此方法可以重复调用
     * 目的:VolumeUtil[创建,销毁]时会涉及一些资源和线程操作;
     * 如果是连续频繁调用(如滑动调节音量),则建议[createGlobalVolumeUtil,releaseGlobalVolumeUtil];
     * 否则每次调用方法时,都是即时[创建和销毁资源]的
     */
    public static native void createGlobalVolumeUtil();

    /**
     * 释放全局变量VolumeUtil;此方法可以重复调用
     */
    public static native void releaseGlobalVolumeUtil();

    /**
     * 查询系统是否静音
     */
    public static native boolean isMute();

    /**
     * 设置系统静音状态
     *
     * @apiNote 系统不会弹出音量提示图案
     */
    public static native void setMute(boolean v);

    /**
     * 获取系统音量
     *
     * @return 范围[0, 100]
     */
    public static native int getVolume();

    /**
     * 设置系统音量,会解除静音状态
     *
     * @param v 范围[0,100],超出范围时会自动靠拢
     * @return 被设置的音量
     * @apiNote 系统不会弹出音量提示图案
     */
    public static native int setVolume(int v);


    //========BatteryUtil

    /**
     * 查询是否连接充电器
     *
     * @return 0-否,1-是,255-未知
     */
    public static native int isAcOnline();

    /**
     * 获取电量值
     *
     * @return [0~100]-正常值,255-未知
     */
    public static native int getBatteryValue();

    //========ShellExecute

    /**
     * ShellExecute的[open]指令,用于[运行程序,用默认浏览器打开网页,打开文件];
     * 目的是代替[java.awt.Desktop#open]无法设置[运行目录]的问题;
     *
     * @param filePath 要打开/执行的文件路径
     * @param runDirectory 运行目录;nullable-在当前目录运行指令
     * @apiNote 原则上[运行程序]时, 都应该传入[程序的父目录], 无奈cpp在获取父目录时十分无语, 所以runDirectory都在java层处理;
     * 打开网页时,如果是新启动的浏览器,则界面缩放比例会错误(不是运行路径问题),暂无解决方法;
     * 获取当前默认浏览器路径 https://blog.csdn.net/ityezi_admin/article/details/26565425
     */
    public static native void shellExecuteOpen(String filePath, String runDirectory, String param);

    /**
     * {@link #shellExecuteOpen(String, String, String)}
     */
    public static void shellExecuteRun(String filePath) throws FileNotFoundException {
        shellExecuteRun(filePath, null);
    }

    /**
     * {@link #shellExecuteOpen(String, String, String)}
     */
    public static void shellExecuteRun(String filePath, String param) throws FileNotFoundException {
        File file = new File(filePath);
        if (!file.exists()) throw new FileNotFoundException(filePath);
        if (!file.isDirectory()) {
            shellExecuteOpen(file.getAbsolutePath(), file.getParentFile().getAbsolutePath(), param);
        } else {
            shellExecuteOpen(file.getAbsolutePath(), null, param);
        }
    }

    /**
     * {@link #shellExecuteOpen(String, String, String)}
     */
    public static void shellExecuteBrowse(URI uri) throws IOException {
        Desktop.getDesktop().browse(uri);
    }

    /**
     * {@link #shellExecuteOpen(String, String, String)}
     */
    public static void shellExecuteBrowse(String url) throws URISyntaxException, IOException {
        Desktop.getDesktop().browse(new URI(url));
    }

}
